<!-- CellCombobox.vue -->
<template>
  <div class="cell-combobox-container">
    <input
        type="text"
        :value="displayValue"
        @input="handleInput"
        @focus="showOptions"
        @blur="handleBlur"
        @click="toggleOptions"
        class="cell-combobox-input"
        ref="input"
    />
    <teleport to="body">
      <div
          v-show="isShowingOptions"
          class="cell-combobox-options"
          :style="optionsStyle"
      >
        <div
            v-for="option in comboboxOptions"
            :key="option.value"
            @mousedown.prevent="selectOption(option)"
            class="cell-combobox-option"
            :class="{
            'selected': option.value === internalValue,
            'highlight': option.label.toLowerCase().includes(userInput.toLowerCase())
          }"
        >
          {{ option.label }}
        </div>
      </div>
    </teleport>
  </div>
</template>

<script>
import { ref, computed, watch, onMounted, onBeforeUnmount, nextTick, inject } from 'vue';

export default {
  name: 'CellCombobox',
  props: {
    modelValue: {
      type: [String, Object],
      default: ''
    },
    comboxlist: {
      type: Object,
      default: () => ({})
    }
  },
  emits: ['update:modelValue', 'focus', 'blur'],
  setup(props, { emit }) {
    const isDev = inject('isDev', false);
    const input = ref(null);
    const isShowingOptions = ref(false);
    const internalValue = ref(props.modelValue);
    const userInput = ref('');
    const optionsStyle = ref({
      position: 'absolute',
      top: '0px',
      left: '0px'
    });

    const fieldNames = computed(() =>
        props.comboxlist.field ? props.comboxlist.field.split(';') : ['value', 'label']
    );

    const defaultField = computed(() => fieldNames.value[0] || 'value');
    const displayField = computed(() =>
        props.comboxlist.displayname || fieldNames.value[1] || defaultField.value
    );
    const returnField = computed(() =>
        props.comboxlist.returndata || defaultField.value
    );

    const comboboxOptions = computed(() => {
      if (props.comboxlist && Array.isArray(props.comboxlist.data)) {
        return props.comboxlist.data.map(item => ({
          value: item[returnField.value] || '',
          label: item[displayField.value] || ''
        }));
      }
      return [];
    });

    const displayValue = computed(() => {
    // if (isDev) console.log('Computing displayValue, userInput is:', userInput.value || 'empty');
      return userInput.value || '';
    });

    const handleInput = (event) => {
      if (isDev) console.log('handleInput called with:', event);
      const inputValue = event.target.value;
      userInput.value = typeof inputValue === 'string' ? inputValue :
          (inputValue && typeof inputValue.toString === 'function' ? inputValue.toString() : '');
      if (isDev) console.log('After handleInput, userInput is:', userInput.value);
      showOptions();
    };

    const selectOption = (option) => {
      internalValue.value = option.value;
      userInput.value = option.label;
      if (isDev) console.log('selectOption, current userInput:', userInput.value);
      emit('update:modelValue', option.value);
      hideOptions();
    };

    const showOptions = () => {
      isShowingOptions.value = true;
      nextTick(() => {
        updateOptionsPosition();
        if (isDev) console.log('Options shown, current userInput:', userInput.value);
      });
    };

    const hideOptions = () => {
      setTimeout(() => {
        isShowingOptions.value = false;
      }, 200);
    };

    const toggleOptions = () => {
      isShowingOptions.value = !isShowingOptions.value;
      if (isShowingOptions.value) {
        nextTick(() => {
          updateOptionsPosition();
          if (isDev) console.log('Options toggled, current userInput:', userInput.value);
        });
      }
    };

    const handleBlur = () => {
      if (isDev) console.log('handleBlur:', userInput.value);
      hideOptions();
      const selectedOption = comboboxOptions.value.find(option =>
          option.label.toLowerCase() === userInput.value.toLowerCase()
      );
      if (selectedOption) {
        internalValue.value = selectedOption.value;
        userInput.value = selectedOption.label;
      } else {
        internalValue.value = String(userInput.value);
      }
      emit('update:modelValue', internalValue.value);
    };

    const initializeValue = () => {
      if (props.modelValue !== internalValue.value) {
        internalValue.value = props.modelValue;
        const selectedOption = comboboxOptions.value.find(option => option.value === internalValue.value);
        userInput.value = selectedOption ? selectedOption.label : (internalValue.value || '');
        if (isDev) {
          console.log('initializeValue called with modelValue:', props.modelValue);
          console.log('After initializeValue, userInput is:', userInput.value);
        }
      }
    };

    const updateOptionsPosition = () => {
      if (input.value) {
        const rect = input.value.getBoundingClientRect();
        optionsStyle.value = {
          top: `${rect.bottom + window.scrollY}px`,
          left: `${rect.left + window.scrollX}px`,
          width: `${rect.width}px`,
          position: 'absolute'
        };
      }
    };

    watch(() => props.modelValue, (newValue, oldValue) => {
      if (newValue !== oldValue) {
        console.log('CellCombobox value changed:', { oldValue, newValue });
        initializeValue();
      }
    });

    watch(() => props.comboxlist, () => {
      nextTick(initializeValue);
    }, { deep: true, immediate: true });

    onMounted(() => {
      if (isDev) {
       // console.log('CellCombobox mounted. Comboxlist:', props.comboxlist);
       // console.log('Initial options:', comboboxOptions.value);
      }
      window.addEventListener('resize', updateOptionsPosition);
    });

    onBeforeUnmount(() => {
      window.removeEventListener('resize', updateOptionsPosition);
    });

    return {
      input,
      isShowingOptions,
      internalValue,
      userInput,
      optionsStyle,
      comboboxOptions,
      displayValue,
      handleInput,
      selectOption,
      showOptions,
      hideOptions,
      toggleOptions,
      handleBlur,
      updateOptionsPosition
    };
  }
};
</script>

<style scoped>
.cell-combobox-container {
  position: relative;
  width: 100%;
  height: 100%;
}

.cell-combobox-input {
  width: 100%;
  height: 100%;
  padding: 2px 20px 2px 4px;
  border: none;
  background-color: transparent;
  font-size: inherit;
  line-height: inherit;
}

.cell-combobox-options {
  position: absolute;
  max-height: 200px;
  overflow-y: auto;
  background-color: white;
  border: 1px solid #ccc;
  z-index: 9999;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.cell-combobox-option {
  padding: 5px;
  cursor: pointer;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cell-combobox-option:hover,
.cell-combobox-option.selected {
  background-color: #f0f0f0;
}

.cell-combobox-option.highlight {
  background-color: #e6f7ff;
}

.cell-combobox-container::after {
  content: '\25BC';
  position: absolute;
  top: 50%;
  right: 5px;
  transform: translateY(-50%);
  pointer-events: none;
  font-size: 0.8em;
  color: #007CB2;
}
</style>
